class Table(object):
    def __str__(self):
        pass

    def __init__(self, element_name="", mxd_name=""):
        """
        @Description mxd文件内需要先创建一个方框和一个文字元素，名字设置为同一个值，创建对象时传入`element_name`
        表格会生成在方框相同位置，大小默认自动拉伸

        - param element_name :{string} 表格元素和文字元素的名称，需要预先创建
        - param mxd_name     :{string} {description}

        """
        self.table_element_name = str(element_name)
        self.text_element_name = str(element_name)
        self.target = mxd_name

        self.mxd = object()
        self.table = object()
        self.text = object()

        self.table_w = 0
        self.table_h = 0
        self.table_x = 0
        self.table_y = 0

        self.xy = []
        self.data = []

        self.init()

    # 初始化数据
    def init(self):
        self.mxd = arcpy.mapping.MapDocument(self.target or r"current")
        self.table = arcpy.mapping.ListLayoutElements(self.mxd, "GRAPHIC_ELEMENT", self.table_element_name)[0]
        self.text = arcpy.mapping.ListLayoutElements(self.mxd, "TEXT_ELEMENT", self.text_element_name)[0]

        # 表格大小
        self.table_w = self.table.elementWidth
        self.table_h = self.table.elementHeight

        # 表格位置
        self.table_x = self.table.elementPositionX
        self.table_y = self.table.elementPositionY

        self.clean()

        return self

    def draw_rows(self, data, max_height):
        self.xy = []

        # 设置总行数
        row_num = len(data)

        # 设置行高
        row_h = self.table_h / row_num

        # 限制每行的高度，默认设置为 表格的高度/行的数量
        if not max_height: max_height = self.table_h / row_num
        if row_h > max_height: row_h = max_height


        # 设置每行的初始位置y
        # 默认表格的偏移点是在左下角，所以表格初始坐标需要重新计算并减去内边距
        y = self.table_h - row_h + self.table_y

        # 遍历行，绘制列
        for i in range(0, len(data)):
            each_row = data[i]

            # 绘制行的第一个元素位置
            x = self.table_x

            # 每行列数保持一致
            # col_num = max(map(lambda x:len(x), data))
            col_num = len(each_row)
            col_base_w = self.table_w / col_num

            xy = []
            # 根据数据进行分列
            for each_col in each_row:
                col = self.table.clone("_col")

                col.elementPositionX = x
                col.elementPositionY = y
                col.elementWidth = col_base_w
                col.elementHeight = row_h

                xy.append({"x":x, "y":y, "w":col_base_w, "h":row_h})
                x += col_base_w

            self.xy.append(xy)
            y -= row_h

    def draw_data(self, data, font_size, align_center=True):
        # 左对齐的内边距
        padding = 4
        for i in range(0, len(data)):
            row = data[i]

            # 获取最大数据长度，落实每列的宽度

            for j in range(0, len(row)):
                new_text = self.text.clone("_text")
                new_text.text = data[i][j]
                new_text.fontSize = font_size

                # 垂直居中
                new_text.elementPositionY = self.xy[i][j]["y"] + (self.xy[i][j]["h"] / 2 - new_text.elementHeight / 2)

                # 水平居中
                if align_center:
                    new_text.elementPositionX = self.xy[i][j]["x"] + self.xy[i][j]["w"] / 2 - new_text.elementWidth / 2

                # 左对齐
                else:
                    new_text.elementPositionX = self.xy[i][j]["x"] + padding

    def draw(self, data=None, font_size=30, max_height=0):
        """
        @Description 绘制表格

        - param self       :{params} {description}
        - param data       :{list}   二维数组，每个元素代表一行数据
        - param font_size  :{int}    字体大小
        - param max_height :{int}    如果设置为0，表格每行将均分高度

        returns `{self}` {description}

        """
        if not data : data = self.data

        self.init()

        self.clean()

        self.draw_rows(data, max_height)

        self.draw_data(data, font_size)

        return self

    # 清空表格
    def clean(self):
        if not hasattr(self.mxd, 'title'): return self
        for elm in arcpy.mapping.ListLayoutElements(self.mxd, wildcard='*'+self.table_element_name+"_col*"):
            elm.delete()

        for elm in arcpy.mapping.ListLayoutElements(self.mxd, wildcard='*'+self.text_element_name+"_text*"):
            elm.delete()
        return self

    # 获取数据
    def get_data(self, layer_name, title, fields):
        mxd = self.mxd

        # 获取当前页面驱动的范围
        shape = mxd.dataDrivenPages.pageRow.shape

        # 获取数据驱动图层的几何对象
        data_layer = None
        for each_layer in arcpy.mapping.ListLayers(mxd):
            if each_layer.name == layer_name:
                data_layer = each_layer

        self.data = [ [title], fields ]

        # 遍历
        for row in arcpy.da.SearchCursor(data_layer, ['SHAPE@'] + fields):
            if shape.contains(row[0]):
                # 添加到 data
                self.data.append([row[i] for i in range(1, len(fields) + 1 )])

        return self


fields = [u'编号', u'X坐标', u'Y坐标']
table1 = Table(u'左岸').get_data(layer_name=u'东安江左岸', title=u'控制点（左岸）', fields=fields)
table2 = Table(u'右岸').get_data(layer_name=u'东安江右岸', title=u'控制点（右岸）', fields=fields)
table1.draw(font_size=10)
table2.draw(font_size=10)
